﻿Namespace EIB
    Public MustInherit Class EIBObjectBase

#Region "Operators"
        'Shared Operator =(a As EIBObjectBase, b As EIBObjectBase) As Boolean
        '    Return OperatorEqual(a, b)
        'End Operator

        'Shared Operator <>(a As EIBObjectBase, b As EIBObjectBase) As Boolean
        '    Return OperatorUnequal(a, b)
        'End Operator

        'Protected MustOverride Function OperatorEqual(a As EIBObjectBase, b As EIBObjectBase) As Boolean
        'Protected MustOverride Function OperatorUnequal(a As EIBObjectBase, b As EIBObjectBase) As Boolean
#End Region

#Region "ToString"
        Protected _leftColumnWidth As Integer = 20
        Protected _rightColumnWidth As Integer = 22
        Protected _inlineWidth As Integer = 2


        Public Overrides Function ToString() As String
            Return ToString(0)
        End Function

        Public Overloads Function ToString(inlineLevel As Integer) As String
            Return InfoListToString(ToInfoList())
        End Function

        Public Function InfoListToString() As String
            Return InfoListToString(ToInfoList)
        End Function

        Public Function InfoListToString(list As List(Of InfoBase)) As String
            Dim info As New Text.StringBuilder

            InfoListToString(info, 0, list)

            Return info.ToString
        End Function

        Private Sub InfoListToString(ByRef info As Text.StringBuilder, inlineLevel As Integer, list As List(Of InfoBase))
            For Each item In list
                Select Case item.GetType
                    Case GetType(Info)
                        AddToStringLine(info, inlineLevel, item.Name, item.Value)
                    Case GetType(InfoMessage)
                        AddToStringLine(info, inlineLevel, item.Name)
                    Case GetType(InfoList)
                        AddToStringLine(info, inlineLevel, item.Name, item.Value)
                        AddToStringLine(info, inlineLevel, "{")
                        InfoListToString(info, inlineLevel + 1, DirectCast(item, InfoList).Children)
                        AddToStringLine(info, inlineLevel, "}")
                End Select
            Next
        End Sub

        Private Sub AddToStringLine(ByRef info As Text.StringBuilder, inlineLevel As Integer, Name As String)
            info.AppendLine(String.Format("{0}{1}", Space(_inlineWidth * inlineLevel), TrimString(Name, _leftColumnWidth + _rightColumnWidth - _inlineWidth * inlineLevel + 2))) '+2 = Doppelpunkt + Leerzeichen
        End Sub

        Private Sub AddToStringLine(ByRef info As Text.StringBuilder, inlineLevel As Integer, Name As String, Value As String)
            If String.IsNullOrWhiteSpace(Value) Then
                AddToStringLine(info, inlineLevel, Name)
            Else
                Dim format As String = String.Format("{{0}}{{1,-{0}}}: {{2,{1}}}", _leftColumnWidth - inlineLevel * _inlineWidth, _rightColumnWidth)

                info.AppendLine(String.Format(format, Space(_inlineWidth * inlineLevel), TrimString(Name, _leftColumnWidth - inlineLevel * _inlineWidth), TrimString(Value, _rightColumnWidth)))
            End If
        End Sub

        Private Function TrimString(input As String, maxLength As Integer) As String
            If input.Length > maxLength Then
                Return String.Format("{0}...", input.Substring(0, maxLength - 3))
            Else
                Return input
            End If
        End Function
#End Region


#Region "ToInfo"
        Public MustOverride Function ToInfoList() As List(Of InfoBase)
#End Region
    End Class


    Public MustInherit Class InfoBase
        Private _Name As String = ""
        Private _Value As String = ""


        Sub New(name As String, value As String)
            _Name = name
            _Value = value
        End Sub


        Public ReadOnly Property Name As String
            Get
                Return _Name
            End Get
        End Property

        Public ReadOnly Property Value As String
            Get
                Return _Value
            End Get
        End Property
    End Class

    Public NotInheritable Class Info
        Inherits InfoBase

        Sub New(name As String, value As String)
            MyBase.New(name, value)
        End Sub
    End Class

    Public NotInheritable Class InfoMessage
        Inherits InfoBase

        Sub New(message As String)
            MyBase.New(message, "")
        End Sub
    End Class

    Public NotInheritable Class InfoList
        Inherits InfoBase

        Private _children As List(Of InfoBase)


        Sub New(name As String, value As String, children As List(Of InfoBase))
            MyBase.new(name, value)

            _children = children
        End Sub


        Public ReadOnly Property Children As List(Of InfoBase)
            Get
                Return _children
            End Get
        End Property
    End Class
End Namespace